/*
 *  Copyright 2008-2010 www.jrails.org
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.rails.core.resource;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.rails.core.GLOBAL;
import org.rails.core.db.DSConfig;
import org.rails.core.util.Utils;

@SuppressWarnings({ "unchecked", "serial" })
public abstract class ConfigBuilder extends Properties {
	
	private static Logger logger = Logger.getLogger("ConfigBuilder");
	
	private static Properties RESOURCE = new Properties();
	
	private final static Map<String, DataSource> GLOBAL_DATASOURCE = new HashMap<String, DataSource>();
	
	static {
		try {
			final File folder = Resource.getPackageFile(GLOBAL.CONFIG_FOLDER);
			if (folder != null) {
				final File[] files = folder.listFiles(new ResourceFileFilter());
				for (int i = 0; i < files.length; i++) {
					final Properties p = new Properties();
					p.load(new FileInputStream(files[i]));			
					if (files[i].getName().equals("db.properties")) {
						final List<String> keys = Utils.getKeys(p);
						for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
							final String key = iterator.next();
							final String value = new String(p.getProperty(key,"").getBytes("ISO-8859-1"),"UTF-8");
							RESOURCE.put(key,value);					
						}
						loadDBProps(files[i]);
					}else{
						final String first = files[i].getName().replaceAll(".properties", "");
						final List<String> keys = Utils.getKeys(p);
						for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
							final String key = iterator.next();
							final String value = new String(p.getProperty(key,"").getBytes("ISO-8859-1"),"UTF-8");
							RESOURCE.put(first + "." + key,value);					
						}
					}
					
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}
	
	public ConfigBuilder(){
		super();
		putAll(RESOURCE);		
		RESOURCE = null;
	}
	
	
	private static void loadDBProps(File file) throws Exception {
		final Properties p = new Properties();
		Set<Object> set;
		Iterator<Object> it;
		String key;
		p.load(new FileInputStream(file));
		set = p.keySet();
		it = set.iterator();
		while (it.hasNext()) {
			key = it.next().toString();
			if (key.lastIndexOf(".db") > 0) {
				final String dbFlag = p.getProperty(key);
				final String jndiKey = dbFlag + ".jndi";
				final String dataSourceKey = dbFlag + ".datasource";
				final String driverKey = dbFlag + ".driver";
				final String urlKey = dbFlag + ".url";
				final String usernameKey = dbFlag + ".username";
				final String passwordKey = dbFlag + ".password";
				final String jndi = RESOURCE.getProperty(jndiKey);
				final String dataSource = RESOURCE.getProperty(dataSourceKey);
				final String driver = RESOURCE.getProperty(driverKey);
				final String url = RESOURCE.getProperty(urlKey);
				final String username = RESOURCE.getProperty(usernameKey);
				final String password = RESOURCE.getProperty(passwordKey);
				RESOURCE.remove(key);
				RESOURCE.remove(dbFlag);
				RESOURCE.remove(jndiKey);
				RESOURCE.remove(dataSourceKey);
				RESOURCE.remove(driverKey);
				RESOURCE.remove(urlKey);
				RESOURCE.remove(usernameKey);
				RESOURCE.remove(passwordKey);
				DSConfig dc = null;
				if (jndi != null) {
					dc = new DSConfig(jndi);
				} else {
					dc = new DSConfig(dataSource, driver, url, username,
							password);
				}
				GLOBAL_DATASOURCE.put(key, dc.getDataSource());
			}
		}
	}

	@Override
	public String get(Object key){
		String k = Utils.def(key,"").toString();
		String prop = getProperty(k,"");
		if(!containsKey(k)){
			
			final Pattern p = Pattern.compile("^\\w+\\.");
			final Matcher m = p.matcher(key.toString());
			if(m.find()){
				k = m.replaceFirst(GLOBAL.SYSTEM_DEFAULT_MODEL + ".");
				prop = getProperty(k,"");
			}
		}
		return prop.trim();
	}
	
	public String getConfigValue(String key,String def){
		return Utils.def(get(key), def).toString();
		
	}
	
	public String get(String key, Object... params) {
		return Utils.format(get(key), params);
	}

	public static Map<String,DataSource> getDSMap(){
		return GLOBAL_DATASOURCE;
	}
	
}
